package com.jch.dm6_active_object.example;

import com.jch.dm3_two_phase_termination.reusable_code.AbstractTerminatableThread;
import com.jch.dm3_two_phase_termination.reusable_code.demo.DelegatingTerminatableThread;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public class CaseRunner {

    /*
    * 例子说明：彩信短号模块
    * 功能：实现手机用户向其他用户发送彩信时，接收方的号码可以使用短号。
    *      关键功能-> 在收到发送彩信的请求时，会依据短号查询数据库获取对应的手机号码。
    *      该查询数据库操作可能会失败（数据库故障，可恢复），而造成请求无法被处理。
    *      但该数据库故障可恢复，可以将该彩信消息缓存到磁盘中（IO操作比较耗时，不要在主线程中做），
    *      等待数据库恢复后，再发送。
    * 详情见《Java多线程编程实战指南 设计模式篇》 第98页
    * */

    public static void main(String[] args) {
        int numRequestThreads = Runtime.getRuntime().availableProcessors();
        int targetTPS = 50;
        float duration = 12; // 单位：秒
        final RequestSender reqSender = new RequestSender((int) (duration * targetTPS));
        final Set<AbstractTerminatableThread> requestThreads = new HashSet<>();

        AbstractTerminatableThread requestThread;
        for (int i = 0; i < numRequestThreads; i++) {
            requestThread = DelegatingTerminatableThread.of(reqSender);
            requestThreads.add(requestThread);
            requestThread.start();
        }

        Timer timer = new Timer(true);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Terminating worker threads....");
                for (AbstractTerminatableThread att:requestThreads) {
                    att.terminate(true);
                }
                reqSender.shutdown();
            }
        }, (long) (duration*1000L));
    }

    static class RequestSender implements Runnable{
        final AtomicInteger totalCount = new AtomicInteger();
        private final RequestPersistence persistence;
        private final Attachment attachment;

        public RequestSender(int n){
            totalCount.set(n);
            persistence = AsyncRequestPersistence.getInstance();
            attachment = new Attachment();
            try{
                URL url = CaseRunner.class.getClassLoader().getResource("test.png");
                attachment.setContentType("image/jpeg");
                attachment.setContent(Files.readAllBytes(Paths.get(url.toURI())));
            } catch (URISyntaxException | IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            int remainingCount;
            while((remainingCount = totalCount.getAndDecrement()) > 0){
                MMSDeliverRequest request = new MMSDeliverRequest();
                request.setTransactionID(String.valueOf(remainingCount));
                request.setSenderAddress("13701239876");
                request.setTimeStamp(new Date());
                request.setExpiry((new Date().getTime() + 3600000) / 1000);
                request.setSubject("你好！");
                request.getRecipient().addTo("876");
                request.setAttachment(attachment);
                persistence.store(request);
            }
        }

        public void shutdown(){
            try{
                persistence.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
